<!DOCTYPE html>
<html>
<body>
<p>
Makes sure that document.activeElement returns a shadow host when a element in the correspoinding shadow tree is focused.
</p>
<pre id="console"></pre>
<script>
function describe(obj) {
    if (obj === document)
        return 'top';
    if (obj.defaultView && obj.defaultView.frameElement)
        return describe(obj.defaultView.frameElement);
    return describe(obj.ownerDocument) + '/' + obj.id;
}

function print(s) {
    document.getElementById('console').textContent += s + '\n';
}

function assertActiveElement(doc, expected) {
    if (doc.activeElement === expected)
        print('PASS: ' + describe(doc) + ' document.activeElement is ' + describe(doc.activeElement));
    else
        print('FAIL: ' + describe(doc) + ' document.activeElement is ' + describe(doc.activeElement) + ' but expected ' + describe(expected));
}

if (window.testRunner) {
    testRunner.dumpAsText();

  function appendChildToShadow(shadowHost, child) {
    var shadowRoot = shadowHost.shadowRoot || shadowHost.attachShadow({mode: 'open'});
    return shadowRoot.appendChild(child)
  }

  function appendShadowHost(doc, parent) {
    var shadowHost = doc.createElement('p');
    shadowHost.tabIndex = 1;  // Makes sure that the shadow host is focusable.
    parent = parent || doc.body;
    return parent.appendChild(shadowHost);
  }

  // For readability, I noted a DOM tree which is under the test here.
  //
  // - document (doc0)
  //   - shadow0
  //     - input0
  //   - iframe1 (doc1)
  //     - shadow1
  //       - input1
  //   - shadow2
  //     - shadow2_1
  //       - input2
  //   - shadow3
  //     - iframe3 (doc3)
  //       - input3
  //   - iframe4 (doc4)
  //     - iframe4_1 (doc4_1)
  //       - input4
  var doc0 = document;
  var shadow0 = appendShadowHost(doc0);
  var input0 = appendChildToShadow(shadow0, doc0.createElement('input'));

  var iframe1 = doc0.body.appendChild(doc0.createElement('iframe'));
  var doc1 = iframe1.contentDocument;
  var shadow1 = appendShadowHost(doc1);
  var input1 = appendChildToShadow(shadow1, doc1.createElement('input'));

  var shadow2 = appendShadowHost(doc0);
  var shadow2_1 = appendShadowHost(doc0, shadow2.attachShadow({mode: 'open'}));
  var input2 = appendChildToShadow(shadow2_1, doc0.createElement('input'));

  var shadow3 = appendShadowHost(doc0);
  var iframe3 = appendChildToShadow(shadow3, doc0.createElement('iframe'))
  var doc3 = iframe3.contentDocument;
  var input3 = doc3.body.appendChild(doc3.createElement('input'))

  // Although this subtree (iframe4) doesn't contain any explicit shadow hosts,
  // this might be useful as a reference.
  var iframe4 = doc0.body.appendChild(doc0.createElement('iframe'));
  var doc4 = iframe4.contentDocument;
  var iframe4_1 = doc4.body.appendChild(doc4.createElement('iframe'));
  var doc4_1 = iframe4_1.contentDocument;
  var input4 = doc4_1.body.appendChild(doc4_1.createElement('input'));

  // Set up IDs for logging.
  var elements = ['shadow0','shadow1', 'shadow2', 'shadow2_1', 'shadow3',
                  'input0', 'input1', 'input2', 'input3', 'input4',
                  'iframe1', 'iframe3', 'iframe4', 'iframe4_1'];
  for (var i = 0; i < elements.length; i++) {
    var id = elements[i];
    window[id].id = id;
  }
  var docs = ['doc0', 'doc1', 'doc3', 'doc4', 'doc4_1'];
  for (var i = 0; i < docs.length; i++) {
    var id = docs[i];
    window[id].body.id = id + '_body';
  }

  print('\nFocusing ' + describe(input0));
  input0.focus();
  assertActiveElement(doc0, shadow0);
  assertActiveElement(doc1, doc1.body);
  assertActiveElement(doc3, doc3.body);
  assertActiveElement(doc4, doc4.body);
  assertActiveElement(doc4_1, doc4_1.body);

  print('\nFocusing ' + describe(input1));
  input1.focus();
  assertActiveElement(doc0, iframe1);
  assertActiveElement(doc1, shadow1);
  assertActiveElement(doc3, doc3.body);
  assertActiveElement(doc4, doc4.body);
  assertActiveElement(doc4_1, doc4_1.body);

  print('\nFocusing ' + describe(input2));
  input2.focus();
  assertActiveElement(doc0, shadow2);
  assertActiveElement(doc1, doc1.body);
  assertActiveElement(doc3, doc3.body);
  assertActiveElement(doc4, doc4.body);
  assertActiveElement(doc4_1, doc4_1.body);

  print('\nFocusing ' + describe(input3));
  input3.focus();
  assertActiveElement(doc0, shadow3);
  assertActiveElement(doc1, doc1.body);
  assertActiveElement(doc3, input3);
  assertActiveElement(doc4, doc4.body);
  assertActiveElement(doc4_1, doc4_1.body);

  print('\nFocusing ' + describe(input4));
  input4.focus();
  assertActiveElement(doc0, iframe4);
  assertActiveElement(doc1, doc1.body);
  assertActiveElement(doc3, doc3.body);
  assertActiveElement(doc4, iframe4_1);
  assertActiveElement(doc4_1, input4);
}
</script>
</body>
</html>
